package com.example.template.common.exception;

/**
 * @className: GlobalExceptionHandler
 * @description: 全局异常处理类
 * @author: Kuangkeli
 * @date: 2024/01/14 19:50
 **/
import com.example.template.common.api.ApiCodeConstant;
import com.example.template.common.api.ApiResult;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.validation.BindingResult;
import org.springframework.validation.FieldError;
import org.springframework.web.bind.MethodArgumentNotValidException;
import org.springframework.web.bind.annotation.ControllerAdvice;
import org.springframework.web.bind.annotation.ExceptionHandler;
import org.springframework.web.bind.annotation.ResponseBody;

import javax.validation.ConstraintViolationException;
import java.util.HashMap;
import java.util.Map;

/**
 * 全局异常处理的原理：在独立的一个类中，定义一套对各种异常的处理机制，然后用@ControllerAdvice注解该类，统一对不同位置的不同异常进行处理。
 */

@ControllerAdvice
//@ControllerAdvice 作用为将被@ExceptionHandler修饰的异常处理方法应用与所有的Controller类
public class GlobalExceptionHandler {
    private static Logger log = LoggerFactory.getLogger(GlobalExceptionHandler.class);

    @ResponseBody
    //当抛出自定义异常时由该方法捕获处理 添加自定义异常的异常码及信息返回Result对象
    @ExceptionHandler(GlobalException.class)
    public ApiResult MyExceptionHandler(Exception ex) {
        return  ApiResult.error(((GlobalException)ex).getCode(), ex.getMessage());
    }

    @ResponseBody
    //抛出空指针异常时 日志纪录 返回空指针状态码及信息
    @ExceptionHandler(NullPointerException.class)
    public ApiResult nullPointerExceptionHandler(NullPointerException ex) {
        log.error(ex.getMessage(),ex);
        return ApiResult.error(ApiCodeConstant.RESULT_NULLPOINT_EXCEPTION, ex.toString());
    }

    @ResponseBody
    //通用的未知异常处理
    @ExceptionHandler(Exception.class)
    public ApiResult otherExcptionHandler(Exception ex) {
        log.error(ex.getMessage(), ex);
        return  ApiResult.error(ApiCodeConstant.RESULT_OTHER_EXCEPTION, ex.toString());
    }


    /**
     * 控制器参数校验异常
     * @param ex
     * @return
     */
    @ExceptionHandler({MethodArgumentNotValidException.class})
    @ResponseBody
    public ApiResult handleMethodArgumentNotValidException(MethodArgumentNotValidException ex) {
        Map<String, Object> result = new HashMap<>();
        BindingResult bindingResult = ex.getBindingResult();
        StringBuilder sb = new StringBuilder("参数校验异常  ");
        for (FieldError fieldError : bindingResult.getFieldErrors()) {
            sb.append(fieldError.getField()).append("：").append(fieldError.getDefaultMessage()).append(";");
        }
        String msg = sb.toString();
        return ApiResult.error(ApiCodeConstant.PARAMETER_VALIDATION_ERROR,msg);
    }

    /**
     * Bean约束异常
     * @param ex
     * @return
     */
    @ExceptionHandler({ConstraintViolationException.class})
    @ResponseBody
    public ApiResult handleConstraintViolationException(ConstraintViolationException ex) {

        return ApiResult.error(ApiCodeConstant.PARAMETER_VALIDATION_ERROR,ex.getMessage());
    }

}
